package com.Cychat.chat.util;

import com.Cychat.chat.service.MessageService;
import com.Cychat.commons.entity.pojo.MessageChatRecord;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.websocket.RemoteEndpoint;
import jakarta.websocket.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class WebSocketUtil {
	// HashMap：不支持多线程，并发情况下线程不安全
	public static final Map<String, Session> MESSAGEMAP = new ConcurrentHashMap<>();

	private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
	private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-M-d H:mm");

	// 注入消息服务
	private static MessageService messageService;

	@Autowired
	public WebSocketUtil(MessageService messageService) {
		WebSocketUtil.messageService = messageService;
	}

	/**
	 * 发送给指定的用户
	 * 
	 * @param message
	 */
	public static void sendTo(String message) {
		// 解析数据
		try {
			Map<String, Object> msg = OBJECT_MAPPER.readValue(message, Map.class);
			// 获取对方id
			Object toIdObj = msg.get("toId");
			if (toIdObj == null) {
				// System.err.println("消息缺少目标用户ID (toId)");
				return;
			}
			String toId = toIdObj.toString();

			Object fromIdObj = msg.get("fromId");
			if (fromIdObj == null) {
				System.err.println("消息缺少发送者ID (fromId)");
				return;
			}
			Long senderId = Long.valueOf(fromIdObj.toString());

			Object msgObj = msg.get("msg");
			if (msgObj == null) {
				System.err.println("消息内容为空 (msg)");
				return;
			}
			String content = msgObj.toString();

			String name = "";
			Object nameObj = msg.get("name");
			if (nameObj != null) {
				name = nameObj.toString();
			}

			String headImg = "";
			Object headImgObj = msg.get("headImg");
			if (headImgObj != null) {
				headImg = headImgObj.toString();
			}

			Object timeObj = msg.get("time");
			if (timeObj == null) {
				System.err.println("消息缺少时间戳 (time)");
				return;
			}
			String time = timeObj.toString();

			Long receiverId = Long.valueOf(toId);
			System.out.println("发送消息 - senderId: " + senderId + ", receiverId: " + receiverId);

			// 找到对应session
			Session session = MESSAGEMAP.get(toId);

			// 保存消息到数据库
			Integer savedMsgId = null;
			if (messageService != null) {
				try {
					savedMsgId = messageService.saveMessage(senderId, receiverId, content, 1, 1);
					if (savedMsgId != null) {
						System.out.println("消息已保存到数据库，消息ID: " + savedMsgId);
					} else {
						System.err.println("警告：消息未能保存到数据库（可能是用户不存在），但将继续尝试发送在线消息");
					}
				} catch (Exception e) {
					System.err.println("保存消息到数据库时发生异常: " + e.getMessage());
					e.printStackTrace();
				}
			}

			// 如果用户在线，则直接发送
			if (session != null) {
				// 在线则直接发送，并将该消息标记为已读，避免下次离线推送重复
				sendMessage(session, message);
				if (messageService != null && savedMsgId != null) {
					messageService.markAsRead(savedMsgId);
				}
				System.out.println("消息已发送给在线用户: " + receiverId);
			} else {
				System.out.println("用户不在线，消息已保存到数据库（如果保存成功），等待用户上线后推送");
			}
		} catch (Exception e) {
			System.err.println("发送消息时出错: " + e.getMessage());
			e.printStackTrace();
		}
	}

	/**
	 * 发送通知消息给指定用户
	 * 
	 * @param receiverId   接收者ID
	 * @param senderId     发送者ID
	 * @param content      消息内容
	 * @param senderName   发送者名称
	 * @param senderAvatar 发送者头像
	 * @param messageType  消息类型
	 */
	public static void sendNotificationMessage(Long receiverId, Long senderId, String content,
			String senderName, String senderAvatar, String messageType) {
		// 重载方法，调用带action参数的版本，action默认为null
		sendNotificationMessage(receiverId, senderId, content, senderName, senderAvatar, messageType, null);
	}

	/**
	 * 发送通知消息给指定用户（带action字段）
	 * 
	 * @param receiverId   接收者ID
	 * @param senderId     发送者ID
	 * @param content      消息内容
	 * @param senderName   发送者名称
	 * @param senderAvatar 发送者头像
	 * @param messageType  消息类型
	 * @param action       操作类型（用于区分好友申请和互动消息）
	 */
	public static void sendNotificationMessage(Long receiverId, Long senderId, String content,
			String senderName, String senderAvatar, String messageType, String action) {
		try {
			// 构造消息内容
			Map<String, Object> messageMap = new HashMap<>();
			messageMap.put("id", System.currentTimeMillis() + "");
			messageMap.put("toId", receiverId.toString());
			messageMap.put("fromId", senderId.toString());
			messageMap.put("name", senderName != null ? senderName : "系统通知");
			messageMap.put("headImg", senderAvatar != null ? senderAvatar
					: "https://pet-java-chengdu-123.oss-cn-chengdu.aliyuncs.com/%E7%94%9F%E6%88%90%E5%AE%98%E6%96%B9%E7%8C%AB%E7%8B%97%20logo.png");
			messageMap.put("msg", content);
			messageMap.put("time", new Date().toString());
			messageMap.put("type", "send");
			messageMap.put("messageType", messageType != null ? messageType : "notification");

			// 添加action字段（如果存在）
			if (action != null && !action.isEmpty()) {
				messageMap.put("action", action);
			}

			String message = OBJECT_MAPPER.writeValueAsString(messageMap);

			// 找到对应session
			Session session = MESSAGEMAP.get(receiverId.toString());

			// 如果用户在线，则直接发送
			if (session != null) {
				sendMessage(session, message);
				System.out.println("通知消息已发送给在线用户: " + receiverId);
			} else {
				System.out.println("用户不在线，通知消息将在用户上线后通过API获取");
			}
		} catch (Exception e) {
			System.err.println("发送通知消息时出错: " + e.getMessage());
			e.printStackTrace();
		}
	}

	// 发送消息给客户端
	public static void sendMessage(Session session, String message) {
		if (session != null) {
			final RemoteEndpoint.Basic basic = session.getBasicRemote();
			if (basic != null) {
				try {
					basic.sendText(message);// 发送消息回客户端
				} catch (IOException e) {
					System.err.println("发送消息到客户端时出错: " + e.getMessage());
					e.printStackTrace();
				}
			}
		}
	}

	// 将消息给所有聊天室的人
	// 循环发送
	public static void sendMessageToAll(String message) {
		MESSAGEMAP.forEach((sessionId, session) -> sendMessage(session, message));
	}

	/**
	 * 发送离线消息给用户
	 */
	public static void sendOfflineMessages(String userId) {
		if (messageService != null) {
			// 验证userId是否为有效的数字字符串，避免NumberFormatException
			Long userIdLong;
			try {
				userIdLong = Long.valueOf(userId);
			} catch (NumberFormatException e) {
				System.err.println("无效的用户ID格式: " + userId);
				return;
			}

			List<MessageChatRecord> unreadMessages = messageService.getUnreadMessages(userIdLong);
			Session session = MESSAGEMAP.get(userId);
			if (session != null && !unreadMessages.isEmpty()) {
				try {
					// 发送未读消息给用户
					for (MessageChatRecord record : unreadMessages) {
						// 构造与在线消息一致的格式并发送
						Map<String, Object> messageMap = new HashMap<>();
						messageMap.put("id", String.valueOf(System.currentTimeMillis()));
						messageMap.put("toId", userId);
						messageMap.put("fromId", String.valueOf(record.getSenderId()));
						messageMap.put("name", ""); // 离线消息没有发送者名称
						messageMap.put("headImg", ""); // 离线消息没有头像
						messageMap.put("msg", record.getContent());
						messageMap.put("time", DATE_FORMAT.format(record.getSendTime()));
						messageMap.put("type", "send");

						String message = OBJECT_MAPPER.writeValueAsString(messageMap);
						sendMessage(session, message);
						// 标记为已读
						messageService.markAsRead(record.getMsgId());
					}
				} catch (Exception e) {
					System.err.println("发送离线消息时出错: " + e.getMessage());
					e.printStackTrace();
				}
			}
		}
	}
}